package hq

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"

	lg "stock_ths/log"
)

// 时刻点的数据
type TimeDotData struct {
	TimeDot      string // 时间点 格式 0930 代表 9:30
	NowPrice     string // 现价
	TurnOver     int    // 成交额
	AveragePrice string // 均价
	Volume       int    // 成交量
}
type TimeData struct {
	Name       string     `json:"name"` // 股票简称
	Open       int        `json:"open"`
	Pre        string     `json:"pre"`
	Rt         string     `json:"rt"` // 时间范围
	Stop       int        `json:"stop"`
	TradeTime  []string   `json:"tradeTime"`
	Date       string     `json:"date"`
	Dates      []string   `json:"dates"`
	DotsCount  int        `json:"dotsCount"`
	IsTrading  int        `json:"isTrading"`
	MarketType string     `json:"marketType"`
	Data       string     `json:"data"` // 原始分时数据
	Code       string     // 股票代码
	TimeDot    [][]string // 解析后的分时数据 数组有五个元素 时间点/现价/成交额/均价/成交量
}

func HttpGet(url, cook string) (string, error) {
	r, _ := http.NewRequest("GET", url, nil)
	// rand.Seed(time.Now().UnixNano())
	// a := rand.Intn(10)
	// b := rand.Intn(5)
	// fmt.Println("rand a=", a, ",b=", b)
	r.Header.Set("Accept", "*/*")
	// r.Header.Set("Accept-Encoding", "gzip, deflate")
	r.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
	r.Header.Set("Connection", "keep-alive")
	// r.Header.Set("If-Modified-Since", "Fri, 27 Aug 2021 16:13:58 GMT")
	r.Header.Set("Host", "d.10jqka.com.cn")
	r.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36")
	r.Header.Set("Referer", "http://stockpage.10jqka.com.cn/")
	cookie := &http.Cookie{Name: "v", Value: cook, HttpOnly: true}
	r.AddCookie(cookie)

	resp, err := http.DefaultClient.Do(r)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	return string(body), nil
}

// 获取分时数据
// http://d.10jqka.com.cn/v6/time/hs_603906/defer/last.js
func GetTime(code, cook string) (TimeData, error) {
	url := fmt.Sprintf("http://d.10jqka.com.cn/v6/time/hs_%s/defer/last.js", code)
	data, err := HttpGet(url, cook)
	if err != nil {
		fmt.Println("HttpGet:", err)
		return TimeData{}, err
	}
	i1 := strings.Index(data, "(")
	i2 := strings.Index(data, ")")
	if i1 < 0 || i2 < 0 {
		lg.ELogger.Println("the request data unused! ", data)
		return TimeData{}, errors.New("the request data unused")
	}
	d := data[i1+1 : i2]
	// fmt.Println(d)
	var md map[string]TimeData
	err = json.Unmarshal([]byte(d), &md)
	if err != nil {
		fmt.Println("error:", err, ",d=", d)
		return TimeData{}, err
	}
	for k, v := range md {
		// fmt.Println(k, v)
		kk := fmt.Sprintf("hs_%s", code)
		if kk == k {
			v.Code = code
			ds := strings.Split(v.Data, ";")
			for _, t := range ds {
				ts := strings.Split(t, ",")
				if len(ts) < 4 {
					fmt.Printf("time dot bad data ignore")
					continue
				}
				// ti := ts[0]           // 时间
				// nowPrice := ts[1]     // 现价
				// turnover := ts[2]     // 成交额
				// averagePrice := ts[3] // 均价
				// volume := ts[4]
				// var tdd TimeDotData
				// tdd.TimeDot = ti
				// tdd.NowPrice = nowPrice
				// iturnover, err := strconv.Atoi(turnover)
				// if err != nil {
				// 	fmt.Printf("error:%v\n", err)
				// 	tdd.TurnOver = -1
				// } else {
				// 	tdd.TurnOver = iturnover
				// }
				// tdd.AveragePrice = averagePrice

				// ivolume, err := strconv.Atoi(volume)
				// if err != nil {
				// 	fmt.Printf("error:%v\n", err)
				// 	tdd.Volume = -1
				// } else {
				// 	tdd.Volume = ivolume
				// }

				v.TimeDot = append(v.TimeDot, ts)
			}
			v.Data = ""
			return v, nil
		}
	}

	return TimeData{}, errors.New("no data")
}

type DaysData struct {
	AfterVolumn string      `json:"afterVolumn"`
	Dates       string      `json:"dates"` // 对应每一条数据的日期 用,分割 例如0926,0927
	IssuePrice  string      `json:"issuePrice"`
	MarketType  string      `json:"marketType"`  // 市场类型
	Name        string      `json:"name"`        // 股票简称
	Price       string      `json:"price"`       // 从Start这个时间点开始的所有价格数据，用,分割的每天有4条数据分别为(每天的最低价/开盘价-最低价/最高价-最低价/收盘价-最低价)
	PriceFactor int         `json:"priceFactor"` // 价格数据的因子 实际的Price解析出来的数据要除以该因子
	SortYear    [][]int     `json:"sortYear"`    // 每一年的数据条数 例如 [[2000,63],[2001,238]], 表示 2000年有63条数据， 2001年有238条数据
	Start       string      `json:"start"`       // 开始时间 例如：20000926 数据采集开始于2000年9月26号
	Total       interface{} `json:"total"`       // 总数据量（天数）
	Volumn      string      `json:"volumn"`      // 成交量以,分割的数据
}

// 保存数据数组的大小 数据在数组中的顺序 最低价/开盘价-最低价/最高价-最低价/收盘价-最低价/成交量
var DataArraySize int = 5

// http://d.10jqka.com.cn/v6/line/hs_000155/01/all.js
func GetDays(code, cook string) ([]string, [][]int, error) {
	url := fmt.Sprintf("http://d.10jqka.com.cn/v6/line/hs_%s/01/all.js", code)

	data, err := HttpGet(url, cook)
	if err != nil {
		fmt.Println("HttpGet:", err)
		return []string{}, [][]int{}, err
	}
	i1 := strings.Index(data, "(")
	i2 := strings.Index(data, ")")
	if i1 < 0 || i2 < 0 {
		lg.ELogger.Println("the request data unused!", data)
		return []string{}, [][]int{}, errors.New("the request data unused")
	}
	d := data[i1+1 : i2]

	// lg.ILogger.Println("request data:", d)

	dd := DaysData{}
	err = json.Unmarshal([]byte(d), &dd)
	if err != nil {
		fmt.Println("json.Umarshal:", err, ",d=", d)
		return []string{}, [][]int{}, err
	}

	dates := strings.Split(dd.Dates, ",")
	prices := strings.Split(dd.Price, ",")
	volumns := strings.Split(dd.Volumn, ",")

	datess := []string{}
	values := [][]int{}
	// 已经解析的总数量
	parseTotal := 0
	for _, ys := range dd.SortYear {
		if len(ys) != 2 {
			continue
		}
		year := ys[0]  // 年份
		count := ys[1] // 年份对应的数量

		// prices 是以逗号分隔的每天对应4个价格 最低价/开盘价-最低价/最高价-最低价/收盘价-最低价
		// 所以下面取价格的时候下标是按照这个算法来的
		for i := 0; i < count; i++ {
			date := dates[i+parseTotal]
			l := prices[(i+parseTotal)*4]    // 最低价
			s := prices[(i+parseTotal)*4+1]  // 开盘价与最低价之差
			h := prices[(i+parseTotal)*4+2]  // 最高价与最低价之差
			st := prices[(i+parseTotal)*4+3] // 收盘价与最低价之差
			volumn := volumns[i+parseTotal]  // 成交量

			sdate := fmt.Sprintf("%d%s", year, date)

			il, err := strconv.Atoi(l)
			if err != nil {
				fmt.Println("atoi:", err)
				continue
			}
			if il < 0 {
				continue
			}

			is, err := strconv.Atoi(s)
			if err != nil {
				fmt.Println("atoi:", err)
				continue
			}
			ih, err := strconv.Atoi(h)
			if err != nil {
				fmt.Println("atoi:", err)
				continue
			}
			ist, err := strconv.Atoi(st)
			if err != nil {
				fmt.Println("atoi:", err)
				continue
			}
			ivolumn, err := strconv.Atoi(volumn)
			if err != nil {
				fmt.Println("atoi:", err)
				continue
			}
			vs := []int{il, il + is, il + ih, il + ist, ivolumn}
			values = append(values, vs)
			datess = append(datess, sdate)
			// values = vs
		}

		parseTotal = parseTotal + count
	}

	lg.ILogger.Println("request volumns size=", len(volumns), ",pices size=", len(prices), ",dates size=", len(dates))
	return datess, values, nil
}
